using Microsoft.Expression.Drawing.Core;
using Microsoft.Expression.Media;
using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
namespace Microsoft.Expression.Controls
{
	public abstract class CompositeContentShape : ContentControl, IGeometrySourceParameters, IShape
	{
		public static readonly DependencyProperty FillProperty = DependencyProperty.Register("Fill", typeof(Brush), typeof(CompositeContentShape), new PropertyMetadata(null));
		public static readonly DependencyProperty StrokeProperty = DependencyProperty.Register("Stroke", typeof(Brush), typeof(CompositeContentShape), new PropertyMetadata(null));
		public static readonly DependencyProperty StrokeThicknessProperty = DependencyProperty.Register("StrokeThickness", typeof(double), typeof(CompositeContentShape), new DrawingPropertyMetadata(1.0, DrawingPropertyMetadataOptions.AffectsRender));
		public static readonly DependencyProperty StretchProperty = DependencyProperty.Register("Stretch", typeof(Stretch), typeof(CompositeContentShape), new DrawingPropertyMetadata(1, DrawingPropertyMetadataOptions.AffectsRender));
		public static readonly DependencyProperty StrokeStartLineCapProperty = DependencyProperty.Register("StrokeStartLineCap", typeof(PenLineCap), typeof(CompositeContentShape), new PropertyMetadata(0));
		public static readonly DependencyProperty StrokeEndLineCapProperty = DependencyProperty.Register("StrokeEndLineCap", typeof(PenLineCap), typeof(CompositeContentShape), new PropertyMetadata(0));
		public static readonly DependencyProperty StrokeLineJoinProperty = DependencyProperty.Register("StrokeLineJoin", typeof(PenLineJoin), typeof(CompositeContentShape), new PropertyMetadata(0));
		public static readonly DependencyProperty StrokeMiterLimitProperty = DependencyProperty.Register("StrokeMiterLimit", typeof(double), typeof(CompositeContentShape), new PropertyMetadata(10.0));
		public static readonly DependencyProperty StrokeDashArrayProperty = DependencyProperty.Register("StrokeDashArray", typeof(DoubleCollection), typeof(CompositeContentShape), new PropertyMetadata(null));
		public static readonly DependencyProperty StrokeDashCapProperty = DependencyProperty.Register("StrokeDashCap", typeof(PenLineCap), typeof(CompositeContentShape), new PropertyMetadata(0));
		public static readonly DependencyProperty StrokeDashOffsetProperty = DependencyProperty.Register("StrokeDashOffset", typeof(double), typeof(CompositeContentShape), new PropertyMetadata(0.0));
		public static readonly DependencyProperty InternalContentProperty = DependencyProperty.Register("InternalContent", typeof(object), typeof(CompositeContentShape), new PropertyMetadata(null));
		private IGeometrySource geometrySource;
		private bool realizeGeometryScheduled;
		public event EventHandler RenderedGeometryChanged;
		private Path PartPath
		{
			get;
			set;
		}
		public Brush Fill
		{
			get
			{
				return (Brush)base.GetValue(CompositeContentShape.FillProperty);
			}
			set
			{
				base.SetValue(CompositeContentShape.FillProperty, value);
			}
		}
		public Brush Stroke
		{
			get
			{
				return (Brush)base.GetValue(CompositeContentShape.StrokeProperty);
			}
			set
			{
				base.SetValue(CompositeContentShape.StrokeProperty, value);
			}
		}
		public double StrokeThickness
		{
			get
			{
				return (double)base.GetValue(CompositeContentShape.StrokeThicknessProperty);
			}
			set
			{
				base.SetValue(CompositeContentShape.StrokeThicknessProperty, value);
			}
		}
		public Stretch Stretch
		{
			get
			{
				return (Stretch)base.GetValue(CompositeContentShape.StretchProperty);
			}
			set
			{
				base.SetValue(CompositeContentShape.StretchProperty, value);
			}
		}
		public PenLineCap StrokeStartLineCap
		{
			get
			{
				return (PenLineCap)base.GetValue(CompositeContentShape.StrokeStartLineCapProperty);
			}
			set
			{
				base.SetValue(CompositeContentShape.StrokeStartLineCapProperty, value);
			}
		}
		public PenLineCap StrokeEndLineCap
		{
			get
			{
				return (PenLineCap)base.GetValue(CompositeContentShape.StrokeEndLineCapProperty);
			}
			set
			{
				base.SetValue(CompositeContentShape.StrokeEndLineCapProperty, value);
			}
		}
		public PenLineJoin StrokeLineJoin
		{
			get
			{
				return (PenLineJoin)base.GetValue(CompositeContentShape.StrokeLineJoinProperty);
			}
			set
			{
				base.SetValue(CompositeContentShape.StrokeLineJoinProperty, value);
			}
		}
		public double StrokeMiterLimit
		{
			get
			{
				return (double)base.GetValue(CompositeContentShape.StrokeMiterLimitProperty);
			}
			set
			{
				base.SetValue(CompositeContentShape.StrokeMiterLimitProperty, value);
			}
		}
		public DoubleCollection StrokeDashArray
		{
			get
			{
				return (DoubleCollection)base.GetValue(CompositeContentShape.StrokeDashArrayProperty);
			}
			set
			{
				base.SetValue(CompositeContentShape.StrokeDashArrayProperty, value);
			}
		}
		public PenLineCap StrokeDashCap
		{
			get
			{
				return (PenLineCap)base.GetValue(CompositeContentShape.StrokeDashCapProperty);
			}
			set
			{
				base.SetValue(CompositeContentShape.StrokeDashCapProperty, value);
			}
		}
		public double StrokeDashOffset
		{
			get
			{
				return (double)base.GetValue(CompositeContentShape.StrokeDashOffsetProperty);
			}
			set
			{
				base.SetValue(CompositeContentShape.StrokeDashOffsetProperty, value);
			}
		}
		public Geometry RenderedGeometry
		{
			get
			{
				return this.GeometrySource.Geometry;
			}
		}
		public Thickness GeometryMargin
		{
			get
			{
				if (this.PartPath != null && this.PartPath.get_Data() != null)
				{
					return this.GeometrySource.LogicalBounds.Subtract(this.PartPath.get_Data().get_Bounds());
				}
				return default(Thickness);
			}
		}
		public object InternalContent
		{
			get
			{
				return base.GetValue(CompositeContentShape.InternalContentProperty);
			}
			private set
			{
				base.SetValue(CompositeContentShape.InternalContentProperty, value);
			}
		}
		private IGeometrySource GeometrySource
		{
			get
			{
				IGeometrySource arg_19_0;
				if ((arg_19_0 = this.geometrySource) == null)
				{
					arg_19_0 = (this.geometrySource = this.CreateGeometrySource());
				}
				return arg_19_0;
			}
		}
		public override void OnApplyTemplate()
		{
			base.OnApplyTemplate();
			this.PartPath = Enumerable.FirstOrDefault<Path>(this.FindVisualDesendent((Path child) => child.get_Name() == "PART_Path"));
			this.GeometrySource.InvalidateGeometry(InvalidateGeometryReasons.TemplateChanged);
		}
		protected abstract IGeometrySource CreateGeometrySource();
		public void InvalidateGeometry(InvalidateGeometryReasons reasons)
		{
			if (this.GeometrySource.InvalidateGeometry(reasons))
			{
				base.InvalidateArrange();
			}
		}
		protected override Size ArrangeOverride(Size finalSize)
		{
			if (this.GeometrySource.UpdateGeometry(this, finalSize.Bounds()) && !this.realizeGeometryScheduled)
			{
				this.realizeGeometryScheduled = true;
				base.add_LayoutUpdated(new EventHandler(this.OnLayoutUpdated));
			}
			return base.ArrangeOverride(finalSize);
		}
		private void OnLayoutUpdated(object sender, EventArgs e)
		{
			this.realizeGeometryScheduled = false;
			base.remove_LayoutUpdated(new EventHandler(this.OnLayoutUpdated));
			this.RealizeGeometry();
		}
		private void RealizeGeometry()
		{
			if (this.PartPath != null)
			{
				this.PartPath.set_Data(this.RenderedGeometry.CloneCurrentValue());
				this.PartPath.set_Margin(this.GeometryMargin);
			}
			if (this.RenderedGeometryChanged != null)
			{
				this.RenderedGeometryChanged.Invoke(this, EventArgs.Empty);
			}
		}
		protected override void OnContentChanged(object oldContent, object newContent)
		{
			base.OnContentChanged(oldContent, newContent);
			IFormattable formattable = base.get_Content() as IFormattable;
			string text = base.get_Content() as string;
			if (formattable == null && text == null)
			{
				this.InternalContent = base.get_Content();
				return;
			}
			TextBlock textBlock = this.InternalContent as TextBlock;
			if (textBlock == null)
			{
				textBlock = (this.InternalContent = new TextBlock());
			}
			textBlock.set_TextAlignment(0);
			textBlock.set_TextWrapping(2);
			textBlock.set_TextTrimming(2);
			textBlock.set_Text(text ?? formattable.ToString(null, null));
		}
	}
}
